﻿using System;
using System.Diagnostics;
using System.Windows.Interop;
using Win32API;
using static Win32API.WinApi;

namespace JoinBox.JoinBox_Code.WPF.多文档标签.View
{
    public class EmbedWPF: IDisposable
    {
        /// <summary>
        /// 用于挤出空间给WPF
        /// </summary>
        public HwndSourceParameters Parameters;
        /// <summary>
        /// 句柄
        /// </summary>
        public IntPtr Handle;
        // 嵌入的容器
        HwndSource _hwndSourcea;

        public DocWindow _DocWindow;

        // 事件
        HwndSourceHook _hwndSourceHook;
        /// <summary>
        /// 嵌入WPF到Win32窗体
        /// </summary>
        /// <param name="newWindowName">新窗体名称</param>
        /// <param name="parentWindow">要嵌入的父窗口句柄</param>
        public EmbedWPF(string newWindowName, IntPtr parentWindow)
        {
            Parameters = new HwndSourceParameters(newWindowName)
            {
                ParentWindow = parentWindow
            };
            //设置可嵌入样式
            Parameters.WindowStyle = (int)WS.WS_CHILD | (int)WS.WS_VISIBLE;
            Parameters.ExtendedWindowStyle = (int)WS.WS_EX_TOPMOST;
        }


        /// <summary>
        /// 嵌入控件
        /// </summary>
        /// <param name="docWindow">来源的控件</param>
        /// <param name="hwndSourceHook">事件</param>
        public void Add(DocWindow docWindow)
        {
            _DocWindow = docWindow;

            _hwndSourcea = new HwndSource(Parameters);
            //设置主应用程序UI,嵌入窗体
            _hwndSourcea.RootVisual = _DocWindow;

            //这里的句柄就是相当于win32窗体的句柄了
            // Handle = _hwndSourcea.CreateHandleRef().Handle; //只是为了不回收和Handle一样的
            Handle = _hwndSourcea.Handle;

#if true2 
            HwndSourceHook hwndSourceHook = null;
            //加入事件
            if (hwndSourceHook != null)
            {
                _hwndSourcea.AddHook(Handlwndproc);
            }           
              _hwndSourcea.AutoResized += _hwndSourcea_AutoResized; 
#endif  
        }

        //自动调整大小时候发生
        private void _hwndSourcea_AutoResized(object sender, System.Windows.AutoResizedEventArgs e)
        {

        }

        //WPF事件
        public IntPtr Handlwndproc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                case (int)WM.WM_CREATE:
                    Debug.WriteLine("创建成功");
                    break;

                case (int)WM.WM_PAINT:
                    //RECT r;
                    //WinApi.GetClientRect(_DM_Handle, out r);
                    //WinApi.SetWindowPos(hwnd, new IntPtr(-1),
                    //    r.Left, r.Top, r.Right - r.Left, r.Bottom - r.Top, 0);
                    //WinApi.SetForegroundWindow(hwnd);
                    break;
                default:
                    break;
            }
            return IntPtr.Zero;
        }

        /// <summary>
        /// 前置窗口和刷新背景色
        /// </summary>
        /// <param name="backgroundColor">背景色</param>
        public void SetPos(System.Windows.Media.Color? backgroundColor = null)
        {
            if (_hwndSourcea != null && Handle != IntPtr.Zero)
            {
                if (backgroundColor != null)
                {
                    _hwndSourcea.CompositionTarget.BackgroundColor = backgroundColor.Value;
                }
                else
                {
                    //纯白
                    //var myRgbColor = System.Windows.Media.Color.FromRgb(255, 255, 255);
                    //_hwndSourcea.CompositionTarget.BackgroundColor = myRgbColor;
                }

                // 显示状态,会触发刷新 
                SetWindowPos(Handle);


                // UpdateWindow(Handle);//显示窗体
                // Application.DoEvents();//winform界面处理消息队列,否则会令界面卡黑色边
            }
        }
          
         

        #region Dispose
        public bool Disposed = false;

        /// <summary>
        /// 显式调用Dispose方法,继承IDisposable
        /// </summary>
        public void Dispose()
        {
            //由手动释放
            Dispose(true);
            //通知垃圾回收机制不再调用终结器(析构器)_跑了这里就不会跑析构函数了
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 析构函数,以备忘记了显式调用Dispose方法
        /// </summary> 
        ~EmbedWPF()
        {
            //由系统释放
            Dispose(false);
        }

        //https://kb.cnblogs.com/page/97871/
        /// <summary>
        /// 释放
        /// </summary>
        /// <param name="ing"></param>
        protected virtual void Dispose(bool ing)
        {
            if (Disposed)
            {
                //不重复释放
                return;
            }
            //让类型知道自己已经被释放
            Disposed = true;

            if (_hwndSourcea != null && !_hwndSourcea.IsDisposed)
            {
                //移除事件
                if (_hwndSourceHook != null)
                {
                    _hwndSourcea.RemoveHook(_hwndSourceHook);
                }
                //移除WPF,调用WPF内部委托实现
                _DocWindow?.Action(WPF =>
                {
                    _hwndSourcea.Dispose();
                });
            }
        }
        #endregion

    }
}